package com.atguigu.auth.service.impl;

import com.atguigu.auth.mapper.SysMenuMapper;
import com.atguigu.auth.mapper.SysRoleMenuMapper;
import com.atguigu.auth.service.SysMenuService;
import com.atguigu.auth.service.SysRoleMenuService;
import com.atguigu.auth.utils.MenuHelper;
import com.atguigu.common.config.exception.GuiguException;
import com.atguigu.model.system.SysMenu;
import com.atguigu.model.system.SysRoleMenu;
import com.atguigu.vo.system.AssginMenuVo;
import com.atguigu.vo.system.MetaVo;
import com.atguigu.vo.system.RouterVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu>
    implements SysMenuService {
    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Autowired
    private SysRoleMenuService sysRoleMenuService;

    @Override
    public List<SysMenu> findNodes() {
        List<SysMenu> menuList = list();
        //根据所有的菜单集合，构建带层级关系的菜单集合
        return MenuHelper.buildTree(menuList);
    }

    @Override
    public void removeMenuById(Long id) {
        SysMenu one = getOne(new LambdaQueryWrapper<SysMenu>()
                .eq(SysMenu::getParentId, id));
        if(one != null){
            throw new GuiguException(201,"当前菜单有子菜单，不能删除");
        }
        removeById(id);
    }

    @Override
    public List<SysMenu> findMenuByRoleId(Long roleId) {
        //查询所有启用的菜单
        List<SysMenu> menus = list(new LambdaQueryWrapper<SysMenu>()
                .eq(SysMenu::getStatus,1));
        Map<Long, SysMenu> menuMap = menus.stream().collect(Collectors.toMap(
                SysMenu::getId, menu -> menu, (oldKey, newKey) -> newKey));
        List<Long> menuIds = sysRoleMenuMapper.getMenuIdsByRoleId(roleId);
        for(Long menuId : menuIds){
            SysMenu menu = menuMap.get(menuId);
            if(menu != null)    menu.setSelect(true);
        }
        return MenuHelper.buildTree(menus);
    }

    @Override
    public void doAssign(AssginMenuVo vo) {
        if(vo.getRoleId() == null){
            throw new GuiguException(201,"为角色分配菜单的参数不合法，角色id为null");
        }
        if(CollectionUtils.isEmpty(vo.getMenuIdList())){
            throw new GuiguException(201,"为角色分配菜单的参数不合法，菜单id为空");
        }
        sysRoleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>()
                .eq(SysRoleMenu::getRoleId,vo.getRoleId()));
        List<SysRoleMenu> list = vo.getMenuIdList().stream().map(menuId -> {
            SysRoleMenu rm = new SysRoleMenu();
            rm.setRoleId(vo.getRoleId());
            rm.setMenuId(menuId);
            return rm;
        }).collect(Collectors.toList());
        sysRoleMenuService.saveBatch(list);
    }

    @Override
    public List<RouterVo> findUserMenuListByUserId(Long userId) {
        List<SysMenu> menuList = null;
        if(userId == 1){
            //说明是管理员，查询所有的生效的菜单集合
            menuList = list(new LambdaQueryWrapper<SysMenu>()
                    .eq(SysMenu::getStatus,1)
                    .orderByAsc(SysMenu::getSortValue));
        }else{
            //说明不是管理员，是其他用户
            menuList = this.baseMapper.findMenuListByUserId(userId);
        }
        //将所有的菜单构建成树形结构
        List<SysMenu> menuTreeList = MenuHelper.buildTree(menuList);
        //将树形结构转换成指定类的属性结构
        return buildRouter(menuTreeList);
    }

    /**
     * 根据菜单树形集合构建对应的路由树形集合
     * @param menuTreeList
     * @return
     */
    private List<RouterVo> buildRouter(List<SysMenu> menuTreeList) {
        List<RouterVo> routers = new ArrayList<>();
        for (SysMenu menu : menuTreeList) {
            RouterVo router = new RouterVo();
            router.setHidden(false);
            router.setAlwaysShow(false);
            router.setPath(getRouterPath(menu));
            router.setComponent(menu.getComponent());
            router.setMeta(new MetaVo(menu.getName(), menu.getIcon()));
            List<SysMenu> children = menu.getChildren();
            //如果当前是菜单，需将按钮对应的路由加载出来，如：“角色授权”按钮对应的路由在“系统管理”下面
            if(menu.getType().intValue() == 1) {
                List<SysMenu> hiddenMenuList = children.stream()
                        .filter(item -> !StringUtils.isEmpty(item.getComponent()))
                        .collect(Collectors.toList());
                for (SysMenu hiddenMenu : hiddenMenuList) {
                    RouterVo hiddenRouter = new RouterVo();
                    hiddenRouter.setHidden(true);
                    hiddenRouter.setAlwaysShow(false);
                    hiddenRouter.setPath(getRouterPath(hiddenMenu));
                    hiddenRouter.setComponent(hiddenMenu.getComponent());
                    hiddenRouter.setMeta(new MetaVo(hiddenMenu.getName(), hiddenMenu.getIcon()));
                    routers.add(hiddenRouter);
                }
            } else {
                if (!CollectionUtils.isEmpty(children)) {
                    if(children.size() > 0) {
                        router.setAlwaysShow(true);
                    }
                    router.setChildren(buildRouter(children));
                }
            }
            routers.add(router);
        }
        return routers;
//        List<RouterVo> routerList = new ArrayList<>();
//        for(SysMenu menu : menuTreeList){
//            RouterVo router = new RouterVo();
//            router.setPath(getRouterPath(menu));
//            //判断当前menu是不是隐藏路由，像分配权限按钮这样的，会跳转到别的页面，但路由会隐藏(此处我也不懂)
//            router.setHidden(menu.getType().intValue() == 2 && !StringUtils.isEmpty(menu.getComponent()));
//            router.setComponent(menu.getComponent());
//            router.setMeta(new MetaVo(menu.getName(),menu.getIcon()));
//            List<RouterVo> children = buildRouter(menu.getChildren());
//            router.setChildren(children);
//            router.setAlwaysShow(!CollectionUtils.isEmpty(children));
//            routerList.add(router);
//        }
//        return routerList;
    }

    /**
     * 获取menu的路由地址
     * @param menu
     * @return
     */
    public String getRouterPath(SysMenu menu){
        if(menu.getParentId().intValue() != 0){
            return menu.getPath();
        }
        return "/" + menu.getPath();
    }

    @Override
    public List<String> findUserPermsByUserId(Long userId) {
        List<SysMenu> menuList = new ArrayList<>();
        if(userId.longValue() == 1){
            menuList = list(new LambdaQueryWrapper<SysMenu>()
                    .eq(SysMenu::getStatus,1));
        }else{
            menuList = this.baseMapper.findMenuListByUserId(userId);
        }
        return menuList.stream().filter(menu -> menu.getType() == 2)
                .map(SysMenu::getPerms).collect(Collectors.toList());
    }
}
